#pragma once

class PoomPicture;
class PoomPictureList;

class PoomPictures
{
public:
  static bool Initialize(HWND hWnd, bool sendNotifications, bool delayLoading, bool enableCaching);
  static void Terminate();

  static bool AssignPicture(CEOID oId, const TCHAR* szPicFile);

  static PoomPicture* Add(CEOID oid, int width, int height, bool reset = false);
  static void Remove(CEOID oid);

  static void BeginLoading();

  static bool IsBusy()
  { return isBusy; }

private:
  // THREAD FUNCTIONS
  static DWORD MainThread(LPVOID lpInstance);

  static void GetCacheFileName(TCHAR* fileName);
  static void LoadCache();
  static void SaveCache();
  static bool LoadBitmap(HANDLE hFile, HDC hdc, CEOID& oid, HBITMAP& hBitmap, int& width, int& height);
  static bool LoadBitmap(HANDLE hFile, HDC hdc, HDC hdc1, HDC hdc2, CEOID& oid, HBITMAP& hBitmap, int& width, int& height);
  static bool SaveBitmap(HANDLE hFile, HDC hdc, HDC hdc1, HDC hdc2, CEOID oid, HBITMAP hBitmap);

private:
  // SYNCHRONIZED FUNCTIONS
  static void SyncTerminate(bool terminate);
  static bool SyncIsTerminating();
  static void SyncSetBusy(bool busy);

  static bool SyncHasTasks();
  static bool SyncGetNextItemToLoad(CEOID& oid, int& width, int& height);
  static bool SyncAssignItemPicture(CEOID oid, HBITMAP hbm, int width, int height);
  static void SyncSendLoadNotify(CEOID oid);

private:
  // DATA
  static PoomPictureList pictureList;
  // global
  static bool            isRunning;
  static bool            isTerminating;
  static bool            isBusy;
  static HANDLE          hThread;
  static DWORD           dwThread;
  static HWND            hWnd;
  static bool            sendNotify;
  static bool            delayLoading;
  static bool            enableCaching;
  // sync
  static HANDLE           evtAction;
  static CRITICAL_SECTION csSync;
};

class PoomPicture
{
public:
  CEOID oid;

  bool isActive;
  bool isLoaded;
  bool isLoadedFromCache;

  HBITMAP hBitmap;
  int     width;
  int     height;

  PoomPicture()
    : hBitmap(NULL), width(0), height(0),
      isActive(false), isLoaded(false), isLoadedFromCache(false),
      oid(0)
  {}
  ~PoomPicture()
  { if (hBitmap != NULL) DeleteObject(hBitmap); }
};

class PoomPictureList
{
friend class PoomPictureListIter;

private:
  class PoomPictureItem
  {
  public:
    PoomPicture* item;
    PoomPictureItem* next;
  };

public:
  PoomPictureList();
  ~PoomPictureList();

  void Clear();

  PoomPicture* Add(CEOID oid, bool active, bool loaded, bool fromCache, HBITMAP hbm, int width, int height);
  void Remove(CEOID oid);

  PoomPicture* Find(CEOID oid);

  long GetCount();

private:
  PoomPictureItem* first;
  PoomPictureItem* last;
  long count;
};

//
// PoomPictureListIter
//
class PoomPictureListIter
{
public:
  PoomPictureListIter(PoomPictureList& list)
  { curr = list.first; }

  void reset(PoomPictureList& list)
  { curr = list.first; }

  bool next()
  { if (curr) curr = curr->next; return (curr != NULL); }
  bool hasData()
  { return (curr != NULL && curr->item != NULL); }

  PoomPicture* get()
  { if (curr) return curr->item; else return NULL; }
  PoomPicture* operator*()
  { return get(); }
  PoomPicture* operator->()
  { return get(); }

private:
  PoomPictureList::PoomPictureItem* curr;
};